package com.zdp.dubbo.simulate.framework.protocol.http;

import com.zdp.dubbo.simulate.framework.Invocation;
import com.zdp.dubbo.simulate.framework.register.LocalRegister;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 处理请求的逻辑
 * @author ZhengDp
 * @Date 2023/6/4 11:56
 */
public class HttpServerHandler {

    public void handler(HttpServletRequest req, HttpServletResponse res) {
        /*
        * 对于服务提供者而言，要如何处理请求?
        * 目标 ： 让服务提供者知道 该请求 要调用 自己的哪一个方法
        * 1. 接口名 + 2. 方法名 + 3.方法参数类型列表 + 4.方法参数值列表 + 5.Version  ==> 执行一个方法 ==> 定义一个类，封装这四个信息
        *  ==> 消费端需要构造出该类 Invocation ==> 通过网络将该对象 传递到 Provider
        * Provider ==> 解析出该对象 ==> 执行对应的方法 ==> 需要找到对应的接口实现类
        * Provider 如何找到对应的接口实现类？ ==> Provider在启动时，注册接口名与接口实现类映射 ==> Provider就可以通过接口名找到对应的接口实现类
        * 通过反射，执行对应方法
        *
        * 多个实现类问题 ==> 多个版本 ==> 版本号区分
        * */

        try {
            Invocation invocation = (Invocation) new ObjectInputStream(req.getInputStream()).readObject();
            String key = invocation.getInterfaceName() +"-" + invocation.getVersion();
            Class interfaceImpl = LocalRegister.get(key);
            Method method = interfaceImpl.getMethod(invocation.getMethodName(), invocation.getParamTypes());
            String result = (String) method.invoke(interfaceImpl.newInstance(),invocation.getParams());

            IOUtils.write(result,res.getOutputStream());


        } catch (IOException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
                 IllegalAccessException | InstantiationException e) {
            throw new RuntimeException(e);
        }
    }
}
